#!/usr/bin/env python

# content_management_dialog - Content management GUI for Entertainer.
# Copyright (C) 2007 Lauri Taimila
# + following additions Copyright 2008 Joshua Scotton <josh@joshuascotton.com>
#       * added on_button_open_list_clicked
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

__licence__ = "GPLv2"
__copyright__ = "2008, Lauri Taimila and Joshua Scotton"
__author__ = "Lauri Taimila <lauri@taimila.com> and Joshua Scotton <josh@joshuascotton.com>"

import os
import sys
import gtk
import pygtk
import string
import gtk.glade
import ConfigParser
from ConfigParser import ParsingError

from utils.weather import Weather
from backend.core.message import Message
from backend.core.message_bus_proxy import MessageBusProxy
from backend.core.message_type_priority import MessageType
from utils.open_feed_source_dialog import OpenFeedSourceDialog

class ContentManagementDialog:
    """
    This is a content management tool for Entertainer media center application.
    """
    
    # Temporary storage for entered URL
    url = ""

    def __init__(self, stand_alone):
        """
        Initialize content management dialog
        @param stand_alone: Boolean, Is this dialog running as a stand alone process
        """
        self.weather = Weather()
        # Open and parse configuration file
        self.stand_alone = stand_alone
        self.config = ConfigParser.ConfigParser()
        try:
            self.config.readfp(open(os.path.expanduser('~/.entertainer/content.conf')))
        except ParsingError:
            print "Syntax error in configuration file: " + os.path.expanduser('~/.entertainer/content.conf')
            print "Execution aborted!"
            sys.exit(1)
        except IOError:
            print "Configuration file is missing: " + os.path.expanduser('~/.entertainer/content.conf')
            print "Execution aborted!"
            #FIXME: We should create a default setting file if file is missing
            sys.exit(1)
        except:
            print "Unknown error occured when configuration file was loaded!"
            print "Execution aborted!"
            sys.exit(1)
            
        # Load glade UI
        self.gladefile = "utils/glade/entertainer-content-management.glade"
        self.widgets = gtk.glade.XML(self.gladefile)
        
        # Get content management dialog and bind signal callbacks
        self.dialog = self.widgets.get_widget("ContentManagementDialog")
        if (self.dialog):
            callback_dic = { "on_button_open_list_clicked" : self.on_button_open_list_clicked,
                             "on_close_button_clicked" : self.on_close_button_clicked,
                             "on_button_remove_videos_clicked" : self.on_button_remove_videos_clicked,
                             "on_button_add_videos_clicked" : self.on_button_add_videos_clicked,
                             "on_button_edit_videos_clicked" : self.on_button_edit_videos_clicked,
                             "on_checkbutton_video_metadata_toggled" : self.on_checkbutton_video_metadata_toggled,
                             "on_button_add_music_clicked" : self.on_button_add_music_clicked,
                             "on_button_remove_music_clicked" : self.on_button_remove_music_clicked,
                             "on_button_edit_music_clicked" : self.on_button_edit_music_clicked,
                             "on_lyrics_checkbox_toggled" : self.on_lyrics_checkbox_toggled,
                             "on_art_checkbox_toggled" : self.on_art_checkbox_toggled,
                             "on_button_add_images_clicked" : self.on_button_add_images_clicked,
                             "on_button_remove_images_clicked" : self.on_button_remove_images_clicked,
                             "on_button_edit_images_clicked" : self.on_button_edit_images_clicked,
                             "on_button_add_feed_clicked" : self.on_button_add_feed_clicked,
                             "on_button_remove_feed_clicked" : self.on_button_remove_feed_clicked,
                             "on_button_edit_feed_clicked" : self.on_button_edit_feed_clicked,
                             "on_fetch_interval_spinbutton_value_changed" : self.on_fetch_interval_spinbutton_value_changed,
	                         "on_ContentManagementDialog_destroy" : self.on_dialog_closed,
	                         "on_url_dialog_delete_event" : self.on_url_dialog_delete_event,
	                         "on_url_dialog_ok_button_clicked" : self.on_url_dialog_ok_button_clicked,
	                         "on_url_dialog_cancel_button_clicked" : self.on_url_dialog_cancel_button_clicked,
	                         "on_button_video_rebuild_clicked" : self.on_button_video_rebuild_clicked,
	                         "on_button_music_rebuild_clicked" : self.on_button_music_rebuild_clicked,
	                         "on_button_image_rebuild_clicked" : self.on_button_image_rebuild_clicked,
	                         "on_button_feed_rebuild_clicked" : self.on_button_feed_rebuild_clicked,
                             "on_button_add_weather_clicked" : self.on_button_add_weather_clicked,
                             "on_button_remove_weather_clicked" : self.on_button_remove_weather_clicked,
                             "on_weather_display_checkbox_toggled" : self.on_weather_display_checkbox_toggled,
                             "on_weather_metric_checkbox_toggled" : self.on_weather_metric_checkbox_toggled,
                             "on_location_find_button_clicked" : self.on_location_find_button_clicked,
                             "on_location_cancel_button_clicked" : self.on_location_cancel_button_clicked,
                             "on_location_add_button_clicked" : self.on_location_add_button_clicked,
                             "on_location_entry_activate" : self.on_location_entry_activate,
                             "on_weather_fetch_interval_spinbutton_value_changed" : self.on_weather_fetch_interval_spinbutton_value_changed }
        self.widgets.signal_autoconnect(callback_dic)
        
        # Initialize dialog widgets with correct values and show dialog
        self.init_dialog_values_from_configure_file()
        self.dialog.resize(500,300)
        self.dialog.show()
        
        # Initialize location list in search dialog
        result_list = self.widgets.get_widget("location_results_treeview")
        store = gtk.ListStore(str, str)
        result_list.set_model(store)
        cell_renderer = gtk.CellRendererText()
        cell_renderer2 = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Code", cell_renderer, text=0)
        column2 = gtk.TreeViewColumn("Location", cell_renderer2, text=1)
        result_list.append_column(column)
        result_list.append_column(column2)

# Signal handlers 

    def on_dialog_closed(self, widget):
        """Callback function for dialog's close button"""
        try:
            proxy = MessageBusProxy(client_name = "Content Management GUI")
            proxy.connectToMessageBus()
            proxy.sendMessage(Message(MessageType.CONTENT_CFG_UPDATED))
            proxy.disconnectFromMessageBus()
        except:
            pass # This means that backend is not running. Doesn't matter
        
        if(self.stand_alone):
            self.dialog.hide()
            self.dialog.destroy()
            gtk.main_quit()
        else:
            self.dialog.hide()
            self.dialog.destroy()
    
    def on_close_button_clicked(self, widget):
        """Callback function for dialog's close button"""
        try:
            proxy = MessageBusProxy(client_name = "Content Management GUI")
            proxy.connectToMessageBus()
            proxy.sendMessage(Message(MessageType.CONTENT_CFG_UPDATED))
            proxy.disconnectFromMessageBus()
        except:
            pass # This means that backend is not running. Doesn't matter
        
        if(self.stand_alone):
            self.dialog.hide()
            self.dialog.destroy()
            gtk.main_quit()
        else:
            self.dialog.hide()
            self.dialog.destroy()
        
    def on_button_add_videos_clicked(self, widget):
        """Opens add URL dialog. """
        widget = self.widgets.get_widget("treeview_videos")
        model = widget.get_model()
        # Open "Select folder" dialog
        dialog =  gtk.FileChooserDialog("Select video folder", None, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK), None)
        status = dialog.run()	
        # If folder was selected we add it to model and update config file
        if(status == gtk.RESPONSE_OK):
            selected_folder = dialog.get_current_folder()
            model.append([selected_folder])
	    if(self.video_folders == None):
			self.video_folders = [selected_folder]
	    else:
            		self.video_folders.append(selected_folder)
            str_folders = string.join(self.video_folders, ';')
            self.config.set("Videos","folders", str_folders)
            cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'), 'w')
            self.config.write(cfg_file)
        dialog.destroy()
        
    def on_button_remove_videos_clicked(self, widget):
        """Remove currently selected folder from video folders"""
        widget = self.widgets.get_widget("treeview_videos")
        model = widget.get_model()
        selection = widget.get_selection().get_selected()
        try:
            rm_folder = model.get_value(selection[1], 0)
            self.video_folders.remove(rm_folder)
            str_folders = string.join(self.video_folders, ';')
            self.config.set("Videos","folders", str_folders)
            cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'), 'w')
            self.config.write(cfg_file)
            model.remove(selection[1])
        except:
            pass
    
    def on_button_edit_videos_clicked(self, widget):
        """Edit currently selected folder"""
        widget = self.widgets.get_widget("treeview_videos")
        url_dialog = self.widgets.get_widget("url_dialog")
        url_entry = self.widgets.get_widget("url_entry")
        model = widget.get_model()
        try:
            selection = widget.get_selection().get_selected()
            folder = model.get_value(selection[1], 0)
            url_entry.set_text(folder)
            url_dialog.set_title("Edit URL")
            status = url_dialog.run()
            if status == gtk.RESPONSE_OK and os.path.exists(self.url):
                # Update list model
                model.set_value(selection[1], 0, self.url)
                # Update configure file
                pos = self.video_folders.index(folder)
                self.video_folders.remove(folder)
                self.video_folders.insert(pos, self.url)
                str_folders = string.join(self.video_folders, ';')
                self.config.set("Videos","folders", str_folders)
                cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'), 'w')
                self.config.write(cfg_file)
        except:
            # No need for actions. Item wasn't selected.
            pass
    
    def on_checkbutton_video_metadata_toggled(self, widget):
        """
        Download video file metadata from internet
        @param widget: GTK-Widget
        """
        self.config.set("Videos","download_metadata", widget.get_active())
        cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'),'w')
        self.config.write(cfg_file)
    
    def on_button_add_music_clicked(self, widget):
        """
        Opens add URL dialog
        @param widget: GTK-Widget
        """
        widget = self.widgets.get_widget("treeview_music")
        model = widget.get_model()
        # Open "Select folder" dialog
        dialog =  gtk.FileChooserDialog("Select music folder", None, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK), None)
        status = dialog.run()
        # If folder was selected we add it to model and update config file
        if(status == gtk.RESPONSE_OK):
            selected_folder = dialog.get_current_folder()
            model.append([selected_folder])
            if(self.music_folders == None):
		self.music_folders = [selected_folder]
	    else:
            	self.music_folders.append(selected_folder)
            str_folders = string.join(self.music_folders, ';')
            self.config.set("Music","folders", str_folders)
            cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'), 'w')
            self.config.write(cfg_file)
        dialog.destroy()
        
    def on_button_remove_music_clicked(self, widget):
        """Remove currently selected folder from music folders"""
        widget = self.widgets.get_widget("treeview_music")
        model = widget.get_model()
        selection = widget.get_selection().get_selected()
        try:
            rm_folder = model.get_value(selection[1], 0)
            self.music_folders.remove(rm_folder)
            str_folders = string.join(self.music_folders, ';')
            self.config.set("Music","folders", str_folders)
            cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'),'w')
            self.config.write(cfg_file)
            model.remove(selection[1])
        except:
            # No need for actions. Item wasn't selected.
            pass
     
    def on_button_edit_music_clicked(self, widget):
        """Edit currently selected music folder"""
        widget = self.widgets.get_widget("treeview_music")
        url_dialog = self.widgets.get_widget("url_dialog")
        url_entry = self.widgets.get_widget("url_entry")
        model = widget.get_model()
        try:
            selection = widget.get_selection().get_selected()
            folder = model.get_value(selection[1], 0)
            url_entry.set_text(folder)
            url_dialog.set_title("Edit URL")
            status = url_dialog.run()
            if status == gtk.RESPONSE_OK and os.path.exists(self.url):
                # Update list model
                model.set_value(selection[1], 0, self.url)
                # Update configure file
                pos = self.music_folders.index(folder)
                self.music_folders.remove(folder)
                self.music_folders.insert(pos, self.url)
                str_folders = string.join(self.music_folders, ';')
                self.config.set("Music","folders", str_folders)
                cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'), 'w')
                self.config.write(cfg_file)
        except:
            # No need for actions. Item wasn't selected.
            pass
    
    def on_button_add_images_clicked(self, widget):
        """Opens add URL dialog. """
        widget = self.widgets.get_widget("treeview_images")
        model = widget.get_model()
        # Open "Select folder" dialog
        dialog =  gtk.FileChooserDialog("Select image folder", None, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK), None)
        status = dialog.run()
        # If folder was selected we add it to model and update config file
        if(status == gtk.RESPONSE_OK):
            selected_folder = dialog.get_current_folder()
            model.append([selected_folder])
	    if(self.image_folders == None):
		self.image_folders = [selected_folder]
            else:
            	self.image_folders.append(selected_folder)
            str_folders = string.join(self.image_folders, ';')
            self.config.set("Images","folders", str_folders)
            cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'), 'w')
            self.config.write(cfg_file)
        dialog.destroy()
        
    def on_button_remove_images_clicked(self, widget):
        """Remove currently selected folder from images folders"""
        widget = self.widgets.get_widget("treeview_images")
        model = widget.get_model()
        selection = widget.get_selection().get_selected()
        try:
            rm_folder = model.get_value(selection[1], 0)
            self.image_folders.remove(rm_folder)
            str_folders = string.join(self.image_folders, ';')
            self.config.set("Images","folders", str_folders)
            cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'),'w')
            self.config.write(cfg_file)
            model.remove(selection[1])
        except:
            # No need for actions. Item wasn't selected.
            pass
    
    def on_button_edit_images_clicked(self, widget):
        """Edit currently selected music folder"""
        widget = self.widgets.get_widget("treeview_images")
        url_dialog = self.widgets.get_widget("url_dialog")
        url_entry = self.widgets.get_widget("url_entry")
        model = widget.get_model()
        try:
            selection = widget.get_selection().get_selected()
            folder = model.get_value(selection[1], 0)
            url_entry.set_text(folder)
            url_dialog.set_title("Edit URL")
            status = url_dialog.run()
            if status == gtk.RESPONSE_OK and os.path.exists(self.url):
                # Update list model
                model.set_value(selection[1], 0, self.url)
                # Update configure file
                pos = self.image_folders.index(folder)
                self.image_folders.remove(folder)
                self.image_folders.insert(pos, self.url)
                str_folders = string.join(self.image_folders, ';')
                self.config.set("Images","folders", str_folders)
                cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'), 'w')
                self.config.write(cfg_file)
        except:
            # No need for actions. Item wasn't selected.
            pass
    
    def on_button_add_feed_clicked(self, widget):
        """Opens add feed dialog. """
        widget = self.widgets.get_widget("treeview_feeds")
        url_dialog = self.widgets.get_widget("url_dialog")
        model = widget.get_model()
        # Open dialog
        url_dialog.set_title("Add RSS-feed")
        status = url_dialog.run()
        # If folder was selected we add it to model and update config file
        if(status == gtk.RESPONSE_OK):
            model.append([self.url])
            self.feeds.append(self.url)
            str_folders = string.join(self.feeds, ';')
            self.config.set("RSS","feeds", str_folders)
            cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'), 'w')
            self.config.write(cfg_file)
            
    def on_button_remove_feed_clicked(self, widget):
        """Remove currently selected reed from RSS-feeds"""
        widget = self.widgets.get_widget("treeview_feeds")
        model = widget.get_model()
        selection = widget.get_selection().get_selected()
        try:
            rm_folder = model.get_value(selection[1], 0)
            self.feeds.remove(rm_folder)
            str_folders = string.join(self.feeds, ';')
            self.config.set("RSS","feeds", str_folders)
            cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'),'w')
            self.config.write(cfg_file)
            model.remove(selection[1])
        except:
            # No need for actions. Item wasn't selected.
            pass
        
    def on_button_edit_feed_clicked(self, widget):
        """Edit currently selected feed"""
        widget = self.widgets.get_widget("treeview_feeds")
        url_dialog = self.widgets.get_widget("url_dialog")
        url_entry = self.widgets.get_widget("url_entry")
        model = widget.get_model()
        try:
            selection = widget.get_selection().get_selected()
            feed = model.get_value(selection[1], 0)
            url_entry.set_text(feed)
            url_dialog.set_title("Edit feed")
            status = url_dialog.run()
            if status == gtk.RESPONSE_OK:
                # Update list model
                model.set_value(selection[1], 0, self.url)
                # Update configure file
                pos = self.feeds.index(feed)
                self.feeds.remove(feed)
                self.feeds.insert(pos, self.url)
                str_feeds = string.join(self.feeds, ';')
                self.config.set("RSS","feeds", str_feeds)
                cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'), 'w')
                self.config.write(cfg_file)
        except:
            # No need for actions. Item wasn't selected.
            pass
    
    def on_button_open_list_clicked(self, widget):
        """Opens the open feed source dialog"""
        OpenFeedSourceDialog(self.widgets.get_widget("treeview_feeds"),self.feeds,self.config)
    
    def on_fetch_interval_spinbutton_value_changed(self, widget):
        self.config.set("RSS","fetch_interval", widget.get_value_as_int())
        cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'),'w')
        self.config.write(cfg_file)

    def on_lyrics_checkbox_toggled(self, widget):
        self.config.set("Music","download_lyrics", widget.get_active())
        cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'),'w')
        self.config.write(cfg_file)
    
    def on_art_checkbox_toggled(self, widget):
        self.config.set("Music","download_album_art", widget.get_active())
        cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'),'w')
        self.config.write(cfg_file)
        
    def on_url_dialog_ok_button_clicked(self, widget):
        """URL dialog OK button pressed. Sets self.url"""
        url_dialog = self.widgets.get_widget("url_dialog")
        url_entry = self.widgets.get_widget("url_entry")
        url_dialog.hide()
        self.url = url_entry.get_text()
        url_entry.set_text("")
        url_dialog.response(gtk.RESPONSE_OK)
        
    def on_url_dialog_cancel_button_clicked(self, widget):
        """URL dialog cancelled. Hides dialog"""
        url_dialog = self.widgets.get_widget("url_dialog")
        url_entry = self.widgets.get_widget("url_entry")
        url_dialog.hide()
        url_entry.set_text("")
        url_dialog.response(gtk.RESPONSE_CANCEL)
        
    def on_url_dialog_delete_event(self, widget, data):
        """Dialog's X clicked. Hides dialog"""
        url_dialog = self.widgets.get_widget("url_dialog")
        url_entry = self.widgets.get_widget("url_entry")
        url_dialog.hide()
        url_entry.set_text("")
        url_dialog.response(gtk.RESPONSE_CANCEL)
        return True
    
    def on_button_add_weather_clicked(self, widget):
        """
        Open location search dialog
        @param widget: GTK-Widget
        """
        add_button = self.widgets.get_widget("location_add_button").set_sensitive(False)
        location_dialog = self.widgets.get_widget("weather_search_dialog")
        location_dialog.set_title("Add location")
        
        # Clear results
        result_list = self.widgets.get_widget("location_results_treeview")
        model = result_list.get_model()        
        model.clear()
        
        status = location_dialog.run()
        if(status == gtk.RESPONSE_OK):
            print "Added"
    
    def on_button_remove_weather_clicked(self, widget):
        """
        Remove currently selected weather location from the location list
        @param widget: GTK-Widget
        """
        widget = self.widgets.get_widget("treeview_locations")
        model = widget.get_model()
        selection = widget.get_selection().get_selected()
        try:
            rm_code = model.get_value(selection[1], 0)
            rm_loc = model.get_value(selection[1], 1)
            rm_str = rm_code + "#" + rm_loc
            self.weather_locations.remove(rm_str)
            str_folders = string.join(self.weather_locations, ';')
            self.config.set("Weather","locations", str_folders)
            cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'),'w')
            self.config.write(cfg_file)
            model.remove(selection[1])
        except:
            # No need for actions. Item wasn't selected.
            pass
    
    def on_weather_display_checkbox_toggled(self, widget):
        """
        Checkbox that defines should we use weather conditions
        @param widget: GTK-Widget
        """
        self.config.set("Weather","display_in_menu", widget.get_active())
        cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'),'w')
        self.config.write(cfg_file)
        if widget.get_active():
            self.widgets.get_widget("button_add_weather").set_sensitive(True)
            self.widgets.get_widget("button_remove_weather").set_sensitive(True)
            self.widgets.get_widget("treeview_locations").set_sensitive(True)
            self.widgets.get_widget("weather_metric_checkbox").set_sensitive(True)
            self.widgets.get_widget("weather_fetch_interval_spinbutton").set_sensitive(True)
        else:
            self.widgets.get_widget("button_add_weather").set_sensitive(False)
            self.widgets.get_widget("button_remove_weather").set_sensitive(False)
            self.widgets.get_widget("treeview_locations").set_sensitive(False)
            self.widgets.get_widget("weather_metric_checkbox").set_sensitive(False)
            self.widgets.get_widget("weather_fetch_interval_spinbutton").set_sensitive(False)
    
    def on_weather_metric_checkbox_toggled(self, widget):
        """
        Checkbox that tells should we use metric untis in weather conditions.
        @param widget: GTK-Widget
        """
        self.config.set("Weather","metric_units", widget.get_active())
        cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'),'w')
        self.config.write(cfg_file)
    
    def on_weather_fetch_interval_spinbutton_value_changed(self, widget):
        """
        Weather fetch spinner value changed
        @param widget: GTK-Widget
        """
        self.config.set("Weather","fetch_interval", widget.get_value_as_int())
        cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'),'w')
        self.config.write(cfg_file)
        
    def on_location_find_button_clicked(self, widget):
        """
        Find location code by search string
        @param widget: GTK-Widget
        """
        add_button = self.widgets.get_widget("location_add_button")
        search_key = self.widgets.get_widget("location_entry").get_text()
        result_list = self.widgets.get_widget("location_results_treeview")
        model = result_list.get_model()        
        model.clear()
        if search_key != "":
            results = self.weather.search(search_key)
            if len(results) > 0:
                add_button.set_sensitive(True)
                for result in results:
                    model.append(result)
                result_list.set_cursor(0)
            else:
                add_button.set_sensitive(False)
                
    def on_location_cancel_button_clicked(self, widget):
        """
        Close location search dialog without taking any actions.
        @param widget: GTK-Widget
        """
        location_dialog = self.widgets.get_widget("weather_search_dialog")
        location_entry = self.widgets.get_widget("location_entry")
        location_dialog.hide()
        location_entry.set_text("")
        location_dialog.response(gtk.RESPONSE_CANCEL)
        
    def on_location_add_button_clicked(self, widget):
        """
        Add selected location to location list and close search dialog
        @param widget: GTK-Widget
        """
        result_list = self.widgets.get_widget("location_results_treeview")
        model = result_list.get_model()
        selection = result_list.get_selection().get_selected()
        location_code = model.get_value(selection[1], 0)
        location_string = model.get_value(selection[1], 1)

        location_list = self.widgets.get_widget("treeview_locations")
        loc_model = location_list.get_model()
        loc_model.append([location_code, location_string])
        
        self.weather_locations.append(location_code + "#" + location_string)
        str_locations = string.join(self.weather_locations, ';')
        self.config.set("Weather","locations", str_locations)
        cfg_file = file(os.path.expanduser('~/.entertainer/content.conf'), 'w')
        self.config.write(cfg_file)
        
        location_dialog = self.widgets.get_widget("weather_search_dialog")
        location_entry = self.widgets.get_widget("location_entry")
        location_dialog.hide()
        location_entry.set_text("")
        location_dialog.response(gtk.RESPONSE_CANCEL)
    
    def on_location_entry_activate(self, widget):
        """
        User hit enter on location entry to start search
        @param widget: GTK-Widget
        """
        self.on_location_find_button_clicked(widget)
    
    def on_button_video_rebuild_clicked(self, widget):
        """
        Rebuild video cache requested
        @param widget: GTK-Widget
        """
        try:
            proxy = MessageBusProxy(client_name = "Content Management GUI")
            proxy.connectToMessageBus()
            proxy.sendMessage(Message(MessageType.REBUILD_VIDEO_CACHE))
            proxy.disconnectFromMessageBus()
        except:
		    # This means that backend is not running. Doesn't matter
		    error = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Entertainer backend is not running. Cache cannot be rebuilt.")
		    error.run()
		    error.destroy()
            
    def on_button_music_rebuild_clicked(self, widget):
        """
        Rebuild music cache requested
        @param widget: GTK-Widget
        """
        try:
            proxy = MessageBusProxy(client_name = "Content Management GUI")
            proxy.connectToMessageBus()
            proxy.sendMessage(Message(MessageType.REBUILD_MUSIC_CACHE))
            proxy.disconnectFromMessageBus()
        except:
		    # This means that backend is not running. Doesn't matter
		    error = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Entertainer backend is not running. Cache cannot be rebuilt.")
		    error.run()
		    error.destroy()
            
    def on_button_image_rebuild_clicked(self, widget):
        """
        Rebuild image cache requested
        @param widget: GTK-Widget
        """
        try:
            proxy = MessageBusProxy(client_name = "Content Management GUI")
            proxy.connectToMessageBus()
            proxy.sendMessage(Message(MessageType.REBUILD_IMAGE_CACHE))
            proxy.disconnectFromMessageBus()
        except:
		    # This means that backend is not running. Doesn't matter
		    error = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Entertainer backend is not running. Cache cannot be rebuilt.")
		    error.run()
		    error.destroy()
            
    def on_button_feed_rebuild_clicked(self, widget):
        """
        Rebuild feed cache requested
        @param widget: GTK-Widget
        """
        #We need the user to confirm the rebuild feed cache request
        dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK_CANCEL, "This will completely remove any feed entries in the cache!")
        status = dialog.run()
        #If user has ok'd the request send the message to the message bus
        if(status == gtk.RESPONSE_OK):
			try:
				proxy = MessageBusProxy(client_name = "Content Management GUI")
				proxy.connectToMessageBus()
				proxy.sendMessage(Message(MessageType.REBUILD_FEED_CACHE))
				proxy.disconnectFromMessageBus()
			except:
			    # This means that backend is not running. Doesn't matter
			    error = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Entertainer backend is not running. Cache cannot be rebuilt.")
			    error.run()
			    error.destroy()
        dialog.destroy()

    
# Signal handlers end       
        
    def init_dialog_values_from_configure_file(self):
        """Read configure file and set dialog widget values with read values."""
        ########################################################################
        # Videos
        ########################################################################
    	videolist_widget = self.widgets.get_widget("treeview_videos")
    	videostore = gtk.ListStore(str)
        folder_list = self.config.get("Videos", "folders") # Error threat
    
    	cell_renderer = gtk.CellRendererText()
    	column = gtk.TreeViewColumn("Folders", cell_renderer, text=0)
    	videolist_widget.append_column(column)
    
    	# If there is no configuration, we don't populate with an empty result
    	if(folder_list.isspace() == True or folder_list == ""):
    		self.video_folders = None
    	else:		
    		self.video_folders = folder_list.split(';')
    
    		# Fill model with folders read from config file
    		for i in range(len(self.video_folders)):
    		    videostore.insert(i, [self.video_folders[i]])
    
    	videolist_widget.set_model(videostore)
        
        # Checkboxes
        metadata_checkbox = self.widgets.get_widget("video_metadata_checkbox")
        if self.config.has_section("Videos"):
            md_val = self.config.getboolean("Videos", "download_metadata") # Error threat
            metadata_checkbox.set_active(md_val)
        
        ########################################################################
        # Music
        ########################################################################
        music_list = self.config.get("Music", "folders") # Error threat
    	musiclist_widget = self.widgets.get_widget("treeview_music")
        music_model = gtk.ListStore(str)
    
    	music_cell = gtk.CellRendererText()
    	music_column = gtk.TreeViewColumn("Folders", music_cell, text=0)
    	musiclist_widget.append_column(music_column)
    
    	# If there is no configuration, we don't populate with an empty result
    	if(music_list.isspace() == True or music_list == ""):
    		self.music_folders = None
    	else:	
    		self.music_folders = music_list.split(';')
    
    		# Fill model with folders read from config file
    		for i in range(len(self.music_folders)):
    		    music_model.insert(i, [self.music_folders[i]])
    
    	musiclist_widget.set_model(music_model)
            
        # Checkboxes
        art_checkbox = self.widgets.get_widget("art_checkbox")
        lyrics_checkbox = self.widgets.get_widget("lyrics_checkbox")
        if self.config.has_section("Music"):
            art_val = self.config.getboolean("Music", "download_album_art") # Error threat
            lyrics_val = self.config.getboolean("Music", "download_lyrics") # Error threat
            art_checkbox.set_active(art_val)
            lyrics_checkbox.set_active(lyrics_val)
        
        ########################################################################
        # Images
        ########################################################################
        image_list = self.config.get("Images", "folders") # Error threat
        imagelist_widget = self.widgets.get_widget("treeview_images")
        images_model = gtk.ListStore(str)

    	img_cell = gtk.CellRendererText()
    	img_column = gtk.TreeViewColumn("Folders", img_cell, text=0)
    	imagelist_widget.append_column(img_column)
    
    	# If there is no configuration, we don't populate with an empty result
    	if(image_list.isspace() == True or image_list == ""):
    		self.image_folders = None
    	else:
    		self.image_folders = image_list.split(';')
    
    		# Fill model with folders read from config file
    		for i in range(len(self.image_folders)):
    		    images_model.insert(i, [self.image_folders[i]])
    
    	imagelist_widget.set_model(images_model)
        
        ########################################################################
        # RSS-feeds
        ########################################################################
        feed_list = self.config.get("RSS", "feeds") # Error threat
        self.feeds = feed_list.split(';')
        
        feedlist_widget = self.widgets.get_widget("treeview_feeds")
        feed_model = gtk.ListStore(str)
        
        rss_cell = gtk.CellRendererText()
        rss_column = gtk.TreeViewColumn("Feeds", rss_cell, text=0)
        feedlist_widget.append_column(rss_column)

        # Fill model with folders read from config file
        for i in range(len(self.feeds)):
            feed_model.insert(i, [self.feeds[i]])

        feedlist_widget.set_model(feed_model)
        
        # Interval spinner
        interval_spinner = self.widgets.get_widget("fetch_interval_spinbutton")
        if self.config.has_section("RSS"):
            interval_val = self.config.getint("RSS", "fetch_interval") # Error threat
            if interval_val < 15:
                interval_val = 15
            elif interval_val > 900:
                interval_val = 900
            interval_spinner.set_value(interval_val)

        ########################################################################
        # Weather locations
        ########################################################################
        location_list = self.config.get("Weather", "locations") # Error threat
        #self.weather_locations = location_list.split(';')
        
        locationlist_widget = self.widgets.get_widget("treeview_locations")
        location_model = gtk.ListStore(str, str)
        
        loc_cell = gtk.CellRendererText()
        location_column = gtk.TreeViewColumn("Code", loc_cell, text=0)
        locationlist_widget.append_column(location_column)
        code_cell = gtk.CellRendererText()
        code_column = gtk.TreeViewColumn("Location", code_cell, text=1)
        locationlist_widget.append_column(code_column)
        
        # If there is no configuration, we don't populate with an empty result
        if(location_list.isspace() == True or location_list == ""):
            self.weather_locations = []
        else:
            self.weather_locations = location_list.split(';')
    
            # Fill model with folders read from config file
            for i in range(len(self.weather_locations)):
                val = self.weather_locations[i]
                code = val[:val.find('#')]
                loc = val[val.find('#') + 1:]
                location_model.insert(i, [code, loc])

        locationlist_widget.set_model(location_model)
        
        # Interval spinner
        interval_spinner = self.widgets.get_widget("weather_fetch_interval_spinbutton")
        if self.config.has_section("Weather"):
            interval_val = self.config.getint("Weather", "fetch_interval") # Error threat
            if interval_val < 15:
                interval_val = 15
            elif interval_val > 900:
                interval_val = 900
            interval_spinner.set_value(interval_val)
            
        # Checkboxes
        weather_metric_checkbox = self.widgets.get_widget("weather_metric_checkbox")
        weather_display_checkbox = self.widgets.get_widget("weather_display_checkbox")
        if self.config.has_section("Weather"):
            metric_val = self.config.getboolean("Weather", "metric_units") # Error threat
            display_val = self.config.getboolean("Weather", "display_in_menu") # Error threat
            weather_metric_checkbox.set_active(metric_val)
            weather_display_checkbox.set_active(display_val)
            if not display_val:
                self.widgets.get_widget("button_add_weather").set_sensitive(False)
                self.widgets.get_widget("button_remove_weather").set_sensitive(False)
                self.widgets.get_widget("treeview_locations").set_sensitive(False)
                self.widgets.get_widget("weather_metric_checkbox").set_sensitive(False)
                self.widgets.get_widget("weather_fetch_interval_spinbutton").set_sensitive(False)
            